<template>
  <div class="lottery-container" :style="backgroundStyle">
    <!-- 添加背景图片上传按钮 -->
    <input 
      type="file" 
      ref="bgImageInput" 
      @change="handleBgImageUpload" 
      accept="image/*"
      style="display: none"
    >
    <!-- 添加背景设置按钮 -->
    <!-- <div class="bg-settings">
      <button @click="triggerBgImageUpload" title="更换背景图片">
        🖼️ 更换背景
      </button>
      <button @click="removeBgImage" v-if="backgroundImage" title="移除背景图片">
        🗑️ 移除背景
      </button>
    </div> -->
    <!-- 添加已中奖列表 -->
    <!-- <div class="winners-list">
      <h3>🏆 中奖名单</h3>
      <div class="winners-scroll">
        <div v-for="(winner, index) in winnersList" :key="index" class="winner-item">
          <span class="winner-number">#{{index + 1}}</span>
          <span class="winner-info">
            <div class="winner-name">{{winner.name}}</div>
            <div class="winner-prize">{{ winner.prizeName || '未知奖项' }}</div>
          </span>
        </div>
      </div>
    </div> -->
    
    <div class="lottery-stage">
      <div ref="container" class="three-container"></div>
      <div class="danmaku-container">
        <div v-for="danmaku in danmakus" :key="danmaku.id" class="danmaku" :style="danmakuStyle(danmaku)">
          {{ danmaku.content }}
        </div>
      </div>
    </div>
    <div class="controls">
      <input 
        type="file" 
        ref="fileInput" 
        @change="handleFileUpload" 
        accept=".xlsx,.xls"
        style="display: none"
      >
      <!-- <button @click="downloadTemplate">下载模板</button> -->
      <!-- <button @click="triggerFileUpload">导入名单</button> -->
      <button @click="togglePrizeConfig">奖品配置</button>
      <!-- <button @click="qrcode-container" style="background-color: brown;width: 100px;"></button> -->
      <!-- <button @click="startLottery" :disabled="!hasParticipants || isLotteryRunning || !currentPrize">开始抽奖</button> -->
      <!-- <button @click="stopLottery" :disabled="!isLotteryRunning">停止抽奖</button> -->
      <button @click="resetLottery" class="reset-btn">重置抽奖</button>
      <!-- <button @click="exportWinnersList" class="export-btn" :disabled="winnersList.length === 0">导出名单</button> -->
      <!-- <button @click="toggleMusic">{{ isMusicPlaying ? '暂停音乐' : '播放音乐' }}</button> -->
    </div>
    <!-- 添加音频元素 -->
    <audio 
      ref="bgMusic" 
      @ended="playNextMusic"
      preload="auto"
      playsinline
      webkit-playsinline
      x5-playsinline
    >
      <source :src="currentMusic" type="audio/mp4">
      <source :src="currentMusic" type="audio/mpeg">
    </audio>
    
    <!-- 添加奖品配置面板 -->
    <div class="prize-config-panel" v-if="showPrizeConfig">
      <div class="panel-header">
        <h3>奖品配置</h3>
        <button @click="showPrizeConfig = false" class="close-btn">×</button>
      </div>
      <div class="panel-body">
        <div v-for="(prize, index) in prizes" :key="index" class="prize-item">
          <div class="prize-header">
            <h4>奖项 {{index + 1}}</h4>
            <button @click="removePrize(index)" class="remove-btn">删除</button>
          </div>
          <div class="prize-form">
            <div class="form-group">
              <label>奖品名称</label>
              <input v-model="prize.name" placeholder="请输入奖品名称" />
            </div>
            <div class="form-group">
              <label>奖品数量</label>
              <input v-model.number="prize.count" type="number" min="1" placeholder="请输入奖品数量" />
            </div>
            <!-- <div class="form-group">
              <label>单次抽取人数</label>
              <input v-model.number="prize.batchCount" type="number" min="1" :max="prize.count" placeholder="请输入单次抽取人数" />
            </div> -->
            <div class="form-group">
              <label>奖品图片</label>
              <input type="file" @change="(e) => handlePrizeImageUpload(e, index)" accept="image/*" />
              <div class="prize-image-preview" v-if="prize.image">
                <img :src="prize.image" alt="奖品图片" />
              </div>
            </div>
          </div>
        </div>
        <button @click="addPrize" class="add-prize-btn">添加奖项</button>
        <button @click="savePrizeConfig" class="save-btn">保存配置</button>
      </div>
    </div>
    
    <!-- 修改批量抽奖弹窗 -->
    <div v-if="showBatchDrawDialog" class="batch-draw-dialog">
      <div class="batch-draw-content">
        <h3>{{ currentPrize?.name }} 抽奖</h3>
        <!-- <p style="color:red">当前奖项: <span class="prize-name">{{currentPrize?.name}}</span></p> -->
        <p style="color:red;font-size: x-large;">奖项总数: <span class="prize-total">{{currentPrize?.count || 0}}</span></p>
        <p style="color:red;font-size: x-large;">已抽数量: <span class="prize-drawn">{{currentPrize?.winners?.length || 0}}</span></p>
        <p style="color:red;font-size: x-large;">剩余数量: <span class="prize-count">{{currentPrize ? (currentPrize.count - (currentPrize.winners?.length || 0)) : 0}}</span></p>
        <div class="batch-input">
          <label>本次抽取人数:</label>
          <input type="number" v-model.number="batchDrawCount" min="1" :max="currentPrize ? (currentPrize.count - (currentPrize.winners?.length || 0)) : 1" />
        </div>
        <div class="batch-actions">
          <button @click="stopLottery(false)" class="confirm-btn">开始抽奖</button>
        </div>
        <button @click="showBatchDrawDialog = false; isLotteryRunning = true;" class="cancel-btn">×</button>
      </div>
    </div>
    
    <!-- 替换原有的中奖提示为批量获奖者显示 -->
    <div v-if="showBatchWinners" class="winner-modal">
      <div class="winner-content">
        <div class="prize-info" v-if="currentBatchPrize">
          <h2>🏆 {{currentBatchPrize.name}} 🏆</h2>
          <div class="prize-image" v-if="currentBatchPrize.image">
            <img :src="currentBatchPrize.image" alt="奖品图片" />
          </div>
        </div>
        <h3 style="color:red;    font-size: xxx-large;">🎉 恭喜中奖 🎉</h3>
        
        <!-- 单个获奖者 -->
        <template v-if="currentBatchWinners.length === 1">
          <p class="winner-name">{{ currentBatchWinners[0].name }}</p>
          <p class="winner-dept">{{ currentBatchWinners[0].department }}</p>
          <!-- <p class="winner-info" v-if="currentBatchWinners[0].employeeId">工号：{{ currentBatchWinners[0].employeeId }}</p> -->
          <!-- <p class="winner-info" v-if="currentBatchWinners[0].phone">电话：{{ currentBatchWinners[0].phone }}</p> -->
        </template>
        
        <!-- 多个获奖者 -->
        <div v-else class="multiple-winners">
          <div v-for="(winner, index) in currentBatchWinners" :key="index" class="batch-winner-item">
            <p class="batch-winner-name">{{ winner.name }}</p>
            <p class="batch-winner-dept">{{ winner.department  }}</p>
      </div>
        </div>
        
        <button @click="startLottery" style="width: 10vw;height: 8vh;font-size: xx-large;">重新开始</button>
      </div>
    </div>
    
    <!-- 添加二维码图片 -->
    <div class="qrcode-container">
      <img src="/static/images/qrcode.png" alt="扫码参与" class="qrcode-image">
    </div>
    <div class="startbutton-container" v-if="isLotteryRunning">
      <button @click="startDraw"></button>
    </div>
    <div class="stopbutton-container" v-if="isHighSpeedRotating">
      <button @click="stopHighSpeedRotation"></button>
    </div>
    <div class="defaultbutton-container" v-if="isLotteryRunning">
      <button @click="startDefaultDraw"></button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import * as THREE from 'three'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { io } from 'socket.io-client'
import gsap from 'gsap'
import axios from 'axios'
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js'
import TWEEN from 'three/examples/jsm/libs/tween.module.js'

const container = ref(null)
const fileInput = ref(null)
const bgMusic = ref(null)
const isMusicPlaying = ref(false)
const isLotteryRunning = ref(false)
const danmakus = ref([])
const historicalDanmakus = ref([])
const winner = ref(null)
const participants = ref([])
const winnersList = ref([])
const isDefault = ref(false)

const hasParticipants = computed(() => participants.value.length > 0)

let scene, camera, renderer
let nameObjects = []
let socket
let currentAnimation
let danmakuLoopTimer
let controls
let currentRotation = { y: 0 }

// 添加状态变量
const currentStatus = ref(0) // 0为初始状态，1为抽奖准备状态，2为抽奖中状态，3为抽奖结束状态
const canOperate = ref(true)
const targets = {
  table: [],
  sphere: [],
  helix: []
}

// 添加背景相关的响应式变量
const bgImageInput = ref(null)
const backgroundImage = ref(null)
const backgroundStyle = computed(() => ({
  backgroundImage: backgroundImage.value ? `url(${backgroundImage.value})` : 'none',
  backgroundSize: 'cover',
  backgroundPosition: 'center',
  backgroundRepeat: 'no-repeat',
  backgroundColor: 'rgba(0, 0, 0, 0.7)'  // 添加半透明黑色背景
}))

// 添加音乐相关的响应式变量
const currentMusicIndex = ref(0)
const musicList = [
  '/audio/01.mp4'
]
const currentMusic = computed(() => musicList[currentMusicIndex.value])

// 添加奖品相关的响应式变量
const prizes = ref([])
const showPrizeConfig = ref(false)
const currentPrizeIndex = ref(0)
const currentPrize = computed(() => {
  if (prizes.value.length === 0) return null
  console.log(prizes.value);
  console.log(currentPrizeIndex.value);
  return prizes.value[currentPrizeIndex.value]
})

// 添加批量抽奖相关变量
const showBatchDrawDialog = ref(false)
const batchDrawCount = ref(1)
const currentBatchWinners = ref([])
const currentBatchPrize = ref(null)
const isHighSpeedRotating = ref(false)

// 添加工具函数
const filterData = (data, rowCount) => {
  const result = []
  for (let i = 0; i < rowCount; i++) {
    for (let j = 0; j < 7; j++) {
      const index = i * 7 + j
      if (index < data.length) {
        result.push({
          ...data[index],
          x: j,
          y: i
        })
      }
    }
  }
  return result
}

const selectCard = (luckyCards, total, id) => {
  let index = Math.floor(Math.random() * total)
  while (luckyCards.includes(index)) {
    index = Math.floor(Math.random() * total)
  }
  return index
}

// 下载Excel模板
const downloadTemplate = async () => {
  try {
    const response = await axios.get('/api/template/download', {
      responseType: 'blob'
    })
    
    // 创建下载链接
    const url = window.URL.createObjectURL(new Blob([response.data]))
    const link = document.createElement('a')
    link.href = url
    link.setAttribute('download', '抽奖名单模板.xlsx')
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
  } catch (error) {
    alert('下载模板失败：' + error.message)
  }
}

// 修改初始化Three.js场景
const initThree = () => {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000)
  renderer = new CSS3DRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  container.value.appendChild(renderer.domElement)

  camera.position.z = 1000  // 减小相机距离，从1500改为1000
  camera.position.y = 0
  camera.lookAt(scene.position)

  controls = new TrackballControls(camera, renderer.domElement)
  controls.rotateSpeed = 1
  controls.staticMoving = true
  controls.minDistance = 100
  controls.maxDistance = 1500  // 减小最大距离
  controls.enabled = false
  controls.addEventListener('change', render)

  // 初始化完成后再获取参与者列表
  loadParticipants()
  
  // 创建不同的布局目标
  createTableVertices()
  createSphereVertices()
  createHelixVertices()
  
  // 直接使用球形布局并开始旋转
  transform(targets.sphere, 1000).then(() => {
    isLotteryRunning.value = true
    currentStatus.value = 2
  })
  
  animate()
}

// 添加布局创建函数
const createTableVertices = () => {
  const tableLen = participants.value.length
  for (let i = 0; i < tableLen; i++) {
    const object = new THREE.Object3D()
    object.position.x = participants.value[i].x * 140 - 490
    object.position.y = -(participants.value[i].y * 180) + 990
    targets.table.push(object)
  }
}

// 修改球面顶点创建函数，确保标签正确朝向
const createSphereVertices = () => {
  targets.sphere = []
  const participantsCount = participants.value.length
  
  if (participantsCount === 0) return
  
  const radius = 600 // 球体半径
  const PI = Math.PI
  
  // 添加随机旋转种子增加随机性
  const randomRotation = Math.random() * 2 * PI
  
  // 黄金螺旋算法 - 确保均匀分布在球面上
  const goldenRatio = (1 + Math.sqrt(5)) / 2
  
  for (let i = 0; i < participantsCount; i++) {
    // 计算极角和方位角
    // 使用黄金比例来确保均匀分布
    const y = 1 - (i / (participantsCount - 1)) * 2  // y 范围从 1 到 -1
    const radius_at_y = Math.sqrt(1 - y * y)         // 在该 y 坐标下的圆半径
    
    // 使用黄金比例递增角度，避免角度聚集
    const theta = 2 * PI * i / goldenRatio
    
    // 计算 x 和 z 坐标
    const x = Math.cos(theta + randomRotation) * radius_at_y
    const z = Math.sin(theta + randomRotation) * radius_at_y
    
    // 创建三维对象
    const object = new THREE.Object3D()
    object.position.set(x * radius, y * radius, z * radius)
    
    // 让标签背面朝向球心，正面朝向外部
    // 计算从球心指向标签位置的方向向量
    const direction = new THREE.Vector3(x, y, z).normalize()
    
    // 创建一个临时向量作为上方向，避免出现奇异点问题
    const up = new THREE.Vector3(0, 1, 0)
    // 如果方向接近垂直向上或向下，使用不同的上方向
    if (Math.abs(y) > 0.9) {
      up.set(1, 0, 0)
    }
    
    // 创建一个四元数，从标准朝向旋转到目标朝向
    const quaternion = new THREE.Quaternion()
    const matrix = new THREE.Matrix4().lookAt(
      new THREE.Vector3(0, 0, 0), // 从球心
      direction.multiplyScalar(-1), // 朝向与direction相反的方向
      up // 上方向
    )
    quaternion.setFromRotationMatrix(matrix)
    
    // 应用旋转
    object.quaternion.copy(quaternion)
    
    targets.sphere.push(object)
  }
}

const createHelixVertices = () => {
  const vector = new THREE.Vector3()
  const helixLen = participants.value.length
  
  for (let i = 0; i < helixLen; i++) {
    const phi = i * 0.175 + Math.PI
    
    const object = new THREE.Object3D()
    object.position.x = 900 * Math.sin(phi)
    object.position.y = -(i * 8) + 450
    object.position.z = 900 * Math.cos(phi)
    
    vector.x = object.position.x * 2
    vector.y = object.position.y
    vector.z = object.position.z * 2
    
    object.lookAt(vector)
    targets.helix.push(object)
  }
}

// 修改变换函数，返回Promise
const transform = (targets, duration) => {
  return new Promise((resolve) => {
    TWEEN.removeAll()
    
    const objects = nameObjects
    for (let i = 0; i < objects.length; i++) {
      const object = objects[i]
      const target = targets[i]
      
      new TWEEN.Tween(object.position)
        .to({
          x: target.position.x,
          y: target.position.y,
          z: target.position.z
        }, Math.random() * duration + duration)
        .easing(TWEEN.Easing.Exponential.InOut)
        .start()
      
      new TWEEN.Tween(object.rotation)
        .to({
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z
        }, Math.random() * duration + duration)
        .easing(TWEEN.Easing.Exponential.InOut)
        .start()
    }
    
    new TWEEN.Tween({})
      .to({}, duration * 2)
      .onUpdate(render)
      .start()
      .onComplete(() => {
        canOperate.value = true
        resolve()
      })
  })
}

//start开始配置抽奖人数
const startDraw = ()=>{
  // 完成旋转后打开批量抽奖确认弹窗
  showBatchDrawDialog.value = true
}


// 修改停止抽奖函数，添加快速旋转动画
const stopLottery = (isSingle) => {
  if (!isLotteryRunning.value) return
  
  isLotteryRunning.value = false
  showBatchDrawDialog.value = false
  

  // 设置高速旋转状态为true
  isHighSpeedRotating.value = true

  if(isSingle==false){
    isDefault.value = false
  }

  // 获取当前旋转角度
  // const currentY = scene.rotation.y
  if (isHighSpeedRotating.value) {
    animateHighSpeedRotation() // 循环调用实现持续旋转
  }
  // 快速顺时针旋转1圈（2π弧度）后再停止
  // new TWEEN.Tween(scene.rotation)
  //   .to({ y: currentY + Math.PI * 12 }, 5000) // 1秒内旋转一圈
  //   .easing(TWEEN.Easing.Quadratic.InOut)
  //   .start()
  //   .onComplete(() => {

      
  //     // // 检查是否还有参与者可以抽奖
  //     // if (participants.value.length === 0) {
  //     //   alert('所有参与者已抽完！')
  //     //   return
  //     // }
      
  //     // // 获取当前奖项
  //     // if (!currentPrize.value) {
  //     //   alert('请先配置奖项！')
  //     //   return
  //     // }
      
  //     // // 计算当前奖项剩余数量
  //     // const remainingPrizeCount = currentPrize.value.count - (currentPrize.value.winners?.length || 0)
  //     // if (remainingPrizeCount <= 0) {
  //     //   // 尝试切换到下一个未抽完的奖项
  //     //   let foundNextPrize = false
  //     //   for (let i = 1; i < prizes.value.length; i++) {
  //     //     const nextIndex = (currentPrizeIndex.value + i) % prizes.value.length
  //     //     const nextPrize = prizes.value[nextIndex]
  //     //     if ((nextPrize.winners?.length || 0) < nextPrize.count) {
  //     //       currentPrizeIndex.value = nextIndex
  //     //       foundNextPrize = true
  //     //       break
  //     //     }
  //     //   }
        
  //     //   if (!foundNextPrize) {
  //     //     alert('所有奖项已抽完！')
  //     //     return
  //     //   }
  //     // }
      
  //     // 设置批量抽奖默认数值为1
  //     // batchDrawCount.value = 1
      
      
  //   })
}

// 添加高速旋转动画函数
const animateHighSpeedRotation = () => {
  if (!isHighSpeedRotating.value) return
  
  const startY = scene.rotation.y
  new TWEEN.Tween(scene.rotation)
    .to({ y: startY + Math.PI * 4 }, 2000) // 2秒旋转2圈
    .easing(TWEEN.Easing.Linear.None)
    .onComplete(() => {
      if (isHighSpeedRotating.value) {
        animateHighSpeedRotation() // 循环调用实现持续旋转
      }
    })
    .start()
}


// 添加停止高速旋转的函数
const stopHighSpeedRotation = () => {
  // 禁用停止按钮，防止多次点击
  isHighSpeedRotating.value = false
  
  // 检查是否还有参与者可以抽奖
  if (participants.value.length === 0) {
    alert('所有参与者已抽完！')
    return
  }
  
  // 获取当前奖项
  if (!currentPrize.value) {
    alert('请先配置奖项！')
    return
  }
  
  // 计算当前奖项剩余数量
  const remainingPrizeCount = currentPrize.value.count - (currentPrize.value.winners?.length || 0)
  if (remainingPrizeCount <= 0) {
    // 尝试切换到下一个未抽完的奖项
    let foundNextPrize = false
    for (let i = 1; i < prizes.value.length; i++) {
      const nextIndex = (currentPrizeIndex.value + i) % prizes.value.length
      const nextPrize = prizes.value[nextIndex]
      if ((nextPrize.winners?.length || 0) < nextPrize.count) {
        currentPrizeIndex.value = nextIndex
        foundNextPrize = true
        break
      }
    }
    
    if (!foundNextPrize) {
      alert('所有奖项已抽完！')
      return
    }
  }
  
  // 获取当前旋转角度和速度
  const currentY = scene.rotation.y
  
  // 创建一个动画效果让球体减速旋转 - 使用缓出效果让球体慢慢停下来
  new TWEEN.Tween(scene.rotation)
    .to({ y: currentY + Math.PI * 2 }, 3000) // 3秒内额外旋转一圈，同时减速
    .easing(TWEEN.Easing.Quadratic.Out) // 使用缓出效果模拟减速
    .start()
    .onComplete(() => {
      // 完全停止后，执行抽奖并显示结果
      executeBatchDraw()
    })
}

// 修改动画循环
const animate = () => {
  requestAnimationFrame(animate)
  
  if (currentStatus.value === 2 && isLotteryRunning.value) {
    scene.rotation.y += 0.01
  }
  
  TWEEN.update()
  controls.update()
  renderer.render(scene, camera)
}

// 添加开始抽奖按钮
const startLottery = async () => {
  if (!canOperate.value || !currentPrize.value) return
  
  // 检查当前奖项是否已抽完
  if (currentPrize.value.winners.length >= currentPrize.value.count) {
    // 尝试切换到下一个未抽完的奖项
    let foundNextPrize = false
    for (let i = 0; i < prizes.value.length; i++) {
      const nextIndex = (currentPrizeIndex.value + i) % prizes.value.length
      const nextPrize = prizes.value[nextIndex]
      if (nextPrize.winners.length < nextPrize.count) {
        currentPrizeIndex.value = nextIndex
        foundNextPrize = true
        break
      }
    }
    
    if (!foundNextPrize) {
      alert('所有奖项已抽完！')
      showBatchWinners.value = false
      return
    }
  }
  
  canOperate.value = false
  isLotteryRunning.value = true
  currentStatus.value = 2
  
  closeBatchWinners();
  // 先变成球形
  await transform(targets.sphere, 800)
}
const startDefaultDraw = ()=>{
  isDefault.value=true;
  stopLottery();
}

// 修改文字元素创建，确保完全复制目标对象的旋转
const createTextElement = (text, index, total) => {
  if (!scene || !camera) {
    console.error('Scene or camera not initialized')
    return null
  }

  const element = document.createElement('div')
  element.className = 'participant-name'
  element.textContent = text

  // 基础样式保留
  const hue = (index * 360 / total) % 360; // 网页6色轮原理
  const saturation = 100 - (index % 20);    // 网页5的饱和度控制
  const lightness = 47 + (index % 15);     // 网页6的明度波动
  
  // 直接在元素上设置内联样式
  element.style.color = '#fff'
  element.style.fontSize = '20px'
  element.style.fontWeight = 'bold'
  element.style.padding = '12px 18px'
  element.style.background = `linear-gradient(
    145deg,
    hsl(${hue}, ${saturation}%, ${lightness}%) 0%,
    hsl(${(hue+30)%360}, ${saturation-10}%, ${lightness+5}%) 100%
  )`;
  element.style.borderRadius = '8px'
  element.style.whiteSpace = 'nowrap'
  element.style.textAlign = 'center'
  // 添加水晶质感（网页5图层样式原理）
  element.style.boxShadow = `
    0 0 15px hsla(${hue}, 50%, 70%, 0.5),
    inset 0 2px 5px rgba(255,255,255,0.3)
  `;
  element.style.margin = '2px'
  element.style.letterSpacing = '1px'
  element.style.backgroundSize = '400% 400%';
  element.style.backgroundPosition = '0% 50%';
  element.style.transition = 'background-position 2s cubic-bezier(0.4,0,0.2,1)';
  element.style.backgroundSize = '400% 400%';
  element.style.backgroundPosition = '0% 50%';
  element.style.transition = 'background-position 2s cubic-bezier(0.4,0,0.2,1)';
  // 添加悬浮交互（参考网页3的动态设计）
  element.addEventListener('mouseenter', () => {
    element.style.backgroundPosition = '100% 50%';
  });
  element.addEventListener('mouseleave', () => {
    element.style.backgroundPosition = '0% 50%'; 
  });
  // element.style.border = '2px solid rgba(0, 0, 0, 0.8)'
  // 添加粒子系统
  createParticleSystem(element);
  // 添加水晶质感（网页5的材质叠加改进）
  // createGlowingLines(element);
  element.style.cssText += `
    box-shadow: 
      0 0 15px rgba(255,255,255,0.8),
      inset 0 0 30px rgba(255,255,255,0.6);
    backdrop-filter: 
      brightness(0.1)
      contrast(0.5);
  `;
  // 动态颜色控制（网页3的Color Over Life原理）
  // const hue = (index * 360 / total) % 360;
  element.querySelectorAll('.element-particles div').forEach(particle => {
    particle.style.background = `
      radial-gradient(
        circle at 30% 30%,
        hsl(${hue}, 100%, 80%),
        hsl(${(hue+30)%360}, 70%, 50%),
        transparent 100%
      )`;
  });

  // createTextElement

  const object = new CSS3DObject(element)
  
  // 让CSS3DObject的位置和旋转与之前计算的sphere位置一致
  if (targets.sphere[index]) {
    object.position.copy(targets.sphere[index].position)
    object.quaternion.copy(targets.sphere[index].quaternion)
  }
  
  

  return object
}

// 在createTextElement函数内，创建元素后添加以下代码
// const createGlowingLines = (element) => {
//   const line = document.createElement('div')
//   line.style.cssText = `
//     position: absolute;
//     width: calc(100% + 12px);
//     height: calc(100% + 12px);
//     top: -6px;
//     left: -6px;
//     border-radius: inherit;
//     background: linear-gradient(
//       45deg,
//       rgba(255,255,255,0) 0%,
//       rgba(255,255,255,1) 50%,
//       rgba(255,255,255,0) 100%
//     );
//     animation: flow 3s linear infinite;
//     filter: drop-shadow(0 0 8px rgba(255,255,255,0.8));
//     clip-path: inset(3px round 12px);
//   `

//   // 动态注入关键帧动画
//   const styleId = 'flow-line-animation'
//   if (!document.getElementById(styleId)) {
//     const style = document.createElement('style')
//     style.id = styleId
//     style.textContent = `
//       @keyframes flow {
//         0% {
//           transform: translateX(-110%) rotate(0deg);
//           opacity: 1;
//         }
//         30% {
//           transform: translateX(110%) rotate(0deg);
//           opacity: 0.8;
//         }
//         31% {
//           transform: translateX(110%) rotate(90deg);
//         }
//         60% {
//           transform: translateX(110%) translateY(110%) rotate(90deg);
//           opacity: 0.6;
//         }
//         61% {
//           transform: translateX(110%) translateY(110%) rotate(180deg);
//         }
//         90% {
//           transform: translateX(-110%) translateY(110%) rotate(180deg);
//           opacity: 0.4;
//         }
//         91% {
//           transform: translateX(-110%) translateY(110%) rotate(270deg);
//         }
//         100% {
//           transform: translateX(-110%) rotate(270deg);
//           opacity: 0;
//         }
//       }
//     `
//     document.head.appendChild(style)
//   }

//   element.appendChild(line)
// }

// 修改updateParticipants函数，确保正确的顺序
const updateParticipants = () => {
  if (!scene) {
    console.error('Scene not initialized')
    return
  }

  // 清除现有的名字对象
  nameObjects.forEach(obj => {
    if (obj) {
      scene.remove(obj)
      if (obj.element && obj.element.parentNode) {
        obj.element.parentNode.removeChild(obj.element)
      }
    }
  })
  nameObjects = []
  
  // 先创建球面顶点，确保分布均匀
  createSphereVertices()
  
  // 然后再创建文字对象
  participants.value.forEach((participant, index) => {
    const object = createTextElement(participant.name, index, participants.value.length)
    if (object) {
      scene.add(object)
      nameObjects.push(object)
    }
  })
}

// 加载参与者列表 - 修改为变量而非常量
let originalLoadParticipants = async () => {
  try {
    const response = await axios.get('/api/users')
    participants.value = response.data
    updateParticipants()
  } catch (error) {
    console.error('获取参与者列表失败:', error)
  }
}

// 使用这个变量作为加载参与者的函数
const loadParticipants = async () => {
  await originalLoadParticipants()
}

// 修改音乐控制函数
const toggleMusic = () => {
  if (!bgMusic.value) return
  
  if (isMusicPlaying.value) {
    bgMusic.value.pause()
  } else {
    bgMusic.value.play()
  }
  isMusicPlaying.value = !isMusicPlaying.value
}

// 添加播放下一首音乐的函数
const playNextMusic = () => {
  currentMusicIndex.value = (currentMusicIndex.value + 1) % musicList.length
  if (isMusicPlaying.value) {
    bgMusic.value.play()
  }
}

// 修改历史弹幕加载函数
const loadHistoryDanmaku = async () => {
  try {
    const response = await axios.get('/api/danmaku/recent')
    if (Array.isArray(response.data)) {
      // 保存最新获取的弹幕ID，用于增量更新
      const latestDanmakuId = response.data.length > 0 
        ? response.data[0].id 
        : 0
      
      historicalDanmakus.value = response.data
      // console.log('成功加载历史弹幕:', historicalDanmakus.value.length, '条')
      
      // 清空当前弹幕列表，重新开始循环播放
      danmakus.value = []
      
      // 保存最新弹幕ID到本地
      localStorage.setItem('latestDanmakuId', latestDanmakuId)
      
      // 重启弹幕循环
      if (danmakuLoopTimer) {
        clearInterval(danmakuLoopTimer)
      }
      startDanmakuLoop()
      
      // 启动定时获取新弹幕
      startDanmakuAutoRefresh()
    }
  } catch (error) {
    // console.error('获取历史弹幕失败:', error)
    // 失败后3秒重试
    setTimeout(loadHistoryDanmaku, 3000)
  }
}

// 添加新的弹幕自动刷新函数
let danmakuRefreshTimer = null
const startDanmakuAutoRefresh = () => {
  // 清除可能存在的旧计时器
  if (danmakuRefreshTimer) {
    clearInterval(danmakuRefreshTimer)
  }
  
  // 每2秒自动刷新一次弹幕数据
  danmakuRefreshTimer = setInterval(async () => {
    try {
      // 获取保存的最新弹幕ID
      const latestId = localStorage.getItem('latestDanmakuId') || 0
      
      // 请求新弹幕，仅获取ID大于最新ID的弹幕
      const response = await axios.get(`/api/danmaku/recent?after=${latestId}`)
      
      if (Array.isArray(response.data) && response.data.length > 0) {
        // console.log('获取到新弹幕:', response.data.length, '条')
        
        // 更新最新弹幕ID
        const newLatestId = response.data[0].id
        localStorage.setItem('latestDanmakuId', newLatestId)
        
        // 将新弹幕添加到历史弹幕列表的前面
        historicalDanmakus.value = [...response.data, ...historicalDanmakus.value]
        
        // 控制历史弹幕总数，避免无限增长
        if (historicalDanmakus.value.length > 50) {
          historicalDanmakus.value = historicalDanmakus.value.slice(0, 50)
        }
      }
    } catch (error) {
      console.error('刷新弹幕失败:', error)
    }
  }, 2000) // 每2秒刷新一次
}

// 修改弹幕循环播放函数
const startDanmakuLoop = () => {
  let currentIndex = 0
  
  danmakuLoopTimer = setInterval(() => {
    if (historicalDanmakus.value.length === 0) {
      // console.log('没有历史弹幕，重新加载')
      loadHistoryDanmaku()
      return
    }
    
    // 每次添加一条弹幕
    const danmaku = historicalDanmakus.value[currentIndex]
    
    if (danmaku) {
      // 创建新的弹幕对象，使用新的ID确保动画正常
      const newDanmaku = {
        ...danmaku,
        id: Date.now() + Math.random()
      }
      
      danmakus.value.push(newDanmaku)
      if (danmakus.value.length > 30) {
        danmakus.value.shift()
      }
      
      // 更新索引，循环播放
      currentIndex = (currentIndex + 1) % historicalDanmakus.value.length
    }
  }, 800) // 每0.8秒发送一条弹幕，增加弹幕密度
}

// 使用计算好的固定轨道
// const TRACKS = Array.from({ length: 15 }, (_, i) => (i * 6 + 5) + '%')
// 修改弹幕样式生成函数
const danmakuStyle = (danmaku) => {
  const randomTop = (typeof danmaku.id === 'number' ? 
    (danmaku.id % 15) * 4 + 5:// 将屏幕分成15份，每份占4%，留5%边距，总体范围缩小到65%
    Math.random() * 60 + 10)  // 随机范围缩小到60%，最低10%最高70%
  
  return {
    color: danmaku.color || '#ffffff',
    top: `${randomTop}%`,
    fontSize: '24px',
    textShadow: '2px 2px 4px rgba(0, 0, 0, 0.7)',
    fontWeight: 'bold',
    whiteSpace: 'nowrap',
    transform: 'translateZ(0)', // 开启硬件加速
    willChange: 'transform',
    // animation: 'danmaku-move 8s linear forwards'  // 确保动画属性正确设置
  }
}

// 添加 render 函数
const render = () => {
  renderer.render(scene, camera)
}

// 窗口大小改变时更新渲染器大小
const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  controls.handleResize()
  render()
}

// 触发文件上传
const triggerFileUpload = () => {
  fileInput.value.click()
}

// 处理文件上传
const handleFileUpload = async (event) => {
  const file = event.target.files[0]
  if (!file) return
  
  const formData = new FormData()
  formData.append('file', file)
  
  try {
    // 修改为正确的API路径
    const response = await axios.post('/api/users/import', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    
    if (response.data) {
      // 上传成功后刷新页面
      window.location.reload()
    } else {
      throw new Error('返回数据格式不正确')
    }
  } catch (error) {
    console.error('上传失败:', error)
    alert('上传失败：' + (error.response?.data?.message || error.message || '服务器错误'))
    // 重置文件输入
    if (fileInput.value) {
      fileInput.value.value = ''
    }
  }
}

// 添加管理批量获奖者显示的变量
const showBatchWinners = ref(false)

// 关闭批量获奖者显示
const closeBatchWinners = () => {

  showBatchWinners.value = false
  
  // 弹窗关闭后才检查是否需要切换奖项
  const remaining = currentPrize.value.count - currentPrize.value.winners.length
  if (remaining <= 0) {
    let foundNextPrize = false
    for (let i = 1; i < prizes.value.length; i++) {
      const nextIndex = (currentPrizeIndex.value + i) % prizes.value.length
      const nextPrize = prizes.value[nextIndex]
      if ((nextPrize.winners?.length || 0) < nextPrize.count) {
        currentPrizeIndex.value = nextIndex
        foundNextPrize = true
        break
      }
    }
    if (!foundNextPrize) {
      alert('所有奖项已抽完！')
    }
  }
  
  // 重置临时变量
  currentBatchPrize.value = null
}

// 替换原有的关闭获奖者窗口函数
const closeWinner = closeBatchWinners

// 触发背景图片上传
const triggerBgImageUpload = () => {
  bgImageInput.value.click()
}

// 处理背景图片上传
const handleBgImageUpload = async (event) => {
  const file = event.target.files[0]
  if (!file) return
  
  const formData = new FormData()
  formData.append('image', file)
  
  try {
    const response = await axios.post('/api/background/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    
    if (response.data && response.data.url) {  // 修改这里，使用 response.data.url
      backgroundImage.value = response.data.url
      // 保存背景图片设置到localStorage
      localStorage.setItem('lotteryBackgroundImage', response.data.url)
    }
  } catch (error) {
    console.error('背景图片上传失败:', error)
    alert('背景图片上传失败：' + (error.response?.data?.message || error.message))
  }
  
  // 重置文件输入
  if (bgImageInput.value) {
    bgImageInput.value.value = ''
  }
}

// 移除背景图片
const removeBgImage = () => {
  backgroundImage.value = null
  localStorage.removeItem('lotteryBackgroundImage')
}

// 添加奖品配置相关函数
const togglePrizeConfig = () => {
  showPrizeConfig.value = !showPrizeConfig.value
}

const addPrize = () => {
  prizes.value.push({
    name: '',
    count: 1,
    image: '',
    winners: [],
    batchCount: 1  // 添加批量抽取人数配置，默认为1
  })
}

const removePrize = (index) => {
  prizes.value.splice(index, 1)
}

// 处理奖品图片上传
const handlePrizeImageUpload = async (event, index) => {
  const file = event.target.files[0]
  if (!file) return
  
  // 先创建本地预览
  const reader = new FileReader()
  reader.onload = (e) => {
    // 使用本地预览URL作为临时图片
    prizes.value[index].image = e.target.result
  }
  reader.readAsDataURL(file)
  
  // 尝试上传到服务器
  const formData = new FormData()
  formData.append('image', file)
  
  try {
    // 使用专门的奖品图片上传接口
    const response = await axios.post('/api/prize/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    
    if (response.data && response.data.url) {
      // 上传成功后，使用服务器返回的URL替换本地预览
      // 确保URL是完整的后端URL
      const backendUrl = response.data.url
      // 如果是开发环境，需要将URL指向后端服务器
      const isDev = window.location.port === '5173' // 开发环境端口
      const fullUrl = isDev 
        ? `http://${window.location.hostname}:3000${backendUrl}` 
        : backendUrl
      
      prizes.value[index].image = fullUrl
      console.log('奖品图片上传成功:', fullUrl)
      
      // 保存更新后的奖品配置
      localStorage.setItem('lotteryPrizes', JSON.stringify(prizes.value))
    }
  } catch (error) {
    console.error('奖品图片上传失败:', error)
    // 上传失败时，保留本地预览，不显示错误提示
    console.log('使用本地预览图片作为替代')
  }
  
  // 重置文件输入
  event.target.value = ''
}

const savePrizeConfig = () => {
  // 验证奖品配置
  const invalidPrizes = prizes.value.filter(prize => !prize.name || prize.count < 1)
  if (invalidPrizes.length > 0) {
    alert('请确保所有奖项都有名称且数量大于0')
    return
  }
  
  // 保存到本地存储
  localStorage.setItem('lotteryPrizes', JSON.stringify(prizes.value))
  showPrizeConfig.value = false
  
  // 重置当前奖项索引
  currentPrizeIndex.value = 0
}

function getSecureRandomIndex(max) {
  // 加密安全核心算法
  const cryptoRandom = () => {
    const buffer = new Uint32Array(1);
    window.crypto.getRandomValues(buffer); // 调用浏览器加密API[1,8](@ref)
    return buffer[0] / (0xFFFFFFFF + 1); // 转换为0-1浮点数[3](@ref)
  };

  // 兼容性降级方案
  const fallbackRandom = () => {
    const mixedEntropy = (Math.random() * 0xFFFF) ^ performance.now(); // 混合熵源增强随机性[3,9](@ref)
    return (mixedEntropy % 0xFFFF) / 0xFFFF;
  };

  try {
    const rand = cryptoRandom(); // 优先使用加密随机[1](@ref)
    return Math.floor(rand * max);
  } catch (e) {
    return Math.floor(fallbackRandom() * max); // 异常时降级方案[3](@ref)
  }
}

// 修改执行批量抽奖函数，保存完整中奖名单到localStorage
const executeBatchDraw = () => {

  // 检查是否还有参与者可以抽奖
  if (participants.value.length === 0) {
    alert('所有参与者已抽完！')
    showBatchDrawDialog.value = false
    return
  }
  
  // 获取当前奖项
  if (!currentPrize.value) {
    alert('请先配置奖项！')
    showBatchDrawDialog.value = false
    return
  }

  // 存储当前奖项信息到临时变量
  currentBatchPrize.value = {...currentPrize.value}
  
  // 计算本次需要抽取的人数
  const remainingPrizeCount = currentPrize.value.count - (currentPrize.value.winners?.length || 0)
  const maxBatchCount = Math.min(
    batchDrawCount.value, // 用户设置的批量抽取数
    remainingPrizeCount, // 不超过当前奖项剩余数量
    participants.value.length // 不超过剩余参与者数量
  )
  
  // 清空当前批次获奖者
  currentBatchWinners.value = []
  let drawCount = maxBatchCount
  if(isDefault.value==true) drawCount=1;

  // 批量抽取获奖者
  for (let i = 0; i < drawCount; i++) {
    // 确保还有参与者
    if (participants.value.length === 0) break
    
    // 选择一名获奖者
    const randomIndex = getSecureRandomIndex(participants.value.length)
    const currentWinner = participants.value[randomIndex]
    
    // 添加奖项信息
    const winnerWithPrize = {
      ...currentWinner,
      prizeName: currentPrize.value.name
    }
    
    // 添加到当前批次获奖者
    currentBatchWinners.value.push(winnerWithPrize)
    
    // 添加到中奖列表
    winnersList.value.push(winnerWithPrize)
    
    // 添加到当前奖项的获奖者列表
    if (!currentPrize.value.winners) {
      currentPrize.value.winners = []
    }
    currentPrize.value.winners.push(winnerWithPrize)
    
    // 从参与者列表中移除
    participants.value = participants.value.filter(p => p.id !== currentWinner.id)
  }
  
  // 关闭批量抽奖弹窗
  showBatchDrawDialog.value = false
  showBatchWinners.value = true
  
  // 更新参与者显示
  updateParticipants()
  
  // 显示获奖者
  if (currentBatchWinners.value.length > 0) {
    showBatchWinners.value = true
  }
  
  // 如果当前奖项已抽完，切换到下一个奖项
  if ((currentPrize.value.winners?.length || 0) >= currentPrize.value.count) {
    // 切换到下一个奖项
    for (let i = 0; i < prizes.value.length; i++) {
      const nextIndex = (currentPrizeIndex.value + i) % prizes.value.length
      const nextPrize = prizes.value[nextIndex]
      if ((nextPrize.winners?.length || 0) < nextPrize.count) {
        currentPrizeIndex.value = nextIndex
        break
      }
    }
  }
  
  // 保存更新后的奖品配置和中奖名单到localStorage
  localStorage.setItem('lotteryPrizes', JSON.stringify(prizes.value))
  localStorage.setItem('lotteryWinners', JSON.stringify(winnersList.value))
}

// 修改重置抽奖函数，同时清空localStorage中的中奖名单
const resetLottery = async () => {
  // 创建确认对话框
  if (!confirm('确定要重置抽奖吗？所有中奖记录将被清空，参与者名单将被还原。')) {
    return
  }
  
  // 停止当前抽奖
  isLotteryRunning.value = false
  
  // 重置奖品配置的获奖者列表
  prizes.value.forEach(prize => {
    prize.winners = []
  })
  
  // 重置当前奖项索引到第一个奖项
  currentPrizeIndex.value = 0
  
  // 清空中奖列表
  winnersList.value = []
  
  // 重新加载参与者列表
  try {
    const response = await axios.get('/api/users')
    participants.value = response.data
    
    // 重新初始化场景
    if (scene) {
      // 清空现有的targets
      targets.table = []
      targets.sphere = []
      targets.helix = []
      
      // 重新创建布局
      createTableVertices()
      createSphereVertices()
      createHelixVertices()
      
      // 更新参与者显示
      updateParticipants()
      
      // 重新开始旋转
      transform(targets.sphere, 1000).then(() => {
        isLotteryRunning.value = true
        currentStatus.value = 2
      })
    }
    
    // 保存重置后的奖品配置
    localStorage.setItem('lotteryPrizes', JSON.stringify(prizes.value))
    // 清空中奖名单
    localStorage.removeItem('lotteryWinners')
    
    alert('抽奖已重置！')
  } catch (error) {
    console.error('重置抽奖失败:', error)
    alert('重置抽奖失败：' + error.message)
  }
}

// 基于网页5的按钮粒子特效改进方案
const createParticleSystem = (parentElement) => {
  const particles = document.createElement('div');
  particles.className = 'element-particles';
  
  // 动态生成12个粒子（网页5的径向渐变改进）
  for(let i=0; i<12; i++){
    const dot = document.createElement('div');
    dot.style.cssText = `
      background: radial-gradient(
        circle at 30% 30%,
        rgba(255,255,255,0.9) 0%,
        rgba(255,200,100,0.6) 50%,
        transparent 70%
      );
      transform: 
        rotate(${i*30}deg)
        translate(20px)
        scale(${Math.random()*0.8+0.2});
      animation: particle-spin ${3+Math.random()*2}s infinite linear;
    `;
    particles.appendChild(dot);
  }
  
  parentElement.appendChild(particles);
}

// 添加导出中奖名单的函数
const exportWinnersList = () => {
  if (winnersList.value.length === 0) {
    alert('暂无中奖记录可导出！')
    return
  }
  
  try {
    // 构造CSV数据
    let csvContent = "序号,姓名,部门,奖项\n"
    
    winnersList.value.forEach((winner, index) => {
      const rowData = [
        index + 1,
        winner.name || '',
        winner.department || '',
        winner.prizeName || '未知奖项'
      ]
      
      // 处理CSV中的特殊字符
      const formattedRowData = rowData.map(field => {
        // 如果字段包含逗号、引号或换行，则用引号包裹并处理内部引号
        if (typeof field === 'string' && (field.includes(',') || field.includes('"') || field.includes('\n'))) {
          return `"${field.replace(/"/g, '""')}"`
        }
        return field
      })
      
      csvContent += formattedRowData.join(',') + '\n'
    })
    
    // 创建CSV Blob并下载
    const blob = new Blob(["\uFEFF" + csvContent], { type: 'text/csv;charset=utf-8;' })
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    const filename = `中奖名单_${new Date().toISOString().slice(0, 10)}.csv`
    
    link.setAttribute('href', url)
    link.setAttribute('download', filename)
    link.style.visibility = 'hidden'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    
    alert('中奖名单导出成功！')
  } catch (error) {
    console.error('导出中奖名单失败:', error)
    alert('导出中奖名单失败：' + error.message)
  }
}

onMounted(async () => {
  console.log('组件挂载')
  
  // 直接设置背景图片
  backgroundImage.value = '/static/images/background.png'
  
  // 初始化音乐播放
  const initMusic = () => {
    if (bgMusic.value) {
      bgMusic.value.volume = 0.5  // 设置音量为50%
      bgMusic.value.play()
        .then(() => {
          isMusicPlaying.value = true
          console.log('音乐开始播放')
        })
        .catch(error => {
          console.log('等待用户交互后开始播放音乐')
        })
    }
  }

  // 添加页面交互事件监听
  const handleUserInteraction = () => {
    if (!isMusicPlaying.value) {
      initMusic()
    }
    // 移除事件监听
    document.removeEventListener('click', handleUserInteraction)
    document.removeEventListener('touchstart', handleUserInteraction)
  }

  // 添加用户交互事件监听
  document.addEventListener('click', handleUserInteraction)
  document.addEventListener('touchstart', handleUserInteraction)
  
  // 尝试初始化音乐（可能会因为浏览器策略而失败）
  initMusic()
  
  // 修改 WebSocket 连接配置
  socket = io('/', {
    reconnection: true,
    reconnectionAttempts: Infinity,  // 无限重连
    reconnectionDelay: 1000,
    transports: ['websocket', 'polling']  // 添加传输方式
  })
  
  socket.on('connect', () => {
    console.log('WebSocket连接成功，socket.id:', socket.id)
    // 连接成功后立即加载历史弹幕
    loadHistoryDanmaku()
  })

  socket.on('connect_error', (error) => {
    console.error('WebSocket连接失败:', error.message)
    // 连接失败后重试加载历史弹幕
    setTimeout(loadHistoryDanmaku, 3000)
  })

  socket.on('disconnect', (reason) => {
    console.log('WebSocket断开连接:', reason)
  })
  
  socket.on('lottery-pool', (users) => {
    console.log('收到用户列表:', users)
    participants.value = users
    if (scene && camera) {
      updateParticipants()
    }
  })

  socket.on('danmaku', (danmaku) => {
    console.log('收到WebSocket弹幕:', danmaku)
    
    // 将新弹幕添加到历史弹幕的开头
    historicalDanmakus.value.unshift(danmaku)
    
    // 更新localStorage中的最新弹幕ID
    if (danmaku.id) {
      localStorage.setItem('latestDanmakuId', danmaku.id)
    }
    
    // 保持最新的50条弹幕
    if (historicalDanmakus.value.length > 50) {
      historicalDanmakus.value = historicalDanmakus.value.slice(0, 50)
    }
  })

  // 初始加载历史弹幕
  await loadHistoryDanmaku()
  
  // 初始化Three.js场景
  initThree()
  
  // 监听键盘事件
  window.addEventListener('keydown', (e) => {
    if ((e.keyCode !== 32 && e.keyCode !== 27) || !canOperate.value) return
    
    if (e.keyCode === 27 && currentStatus.value === 3) {
      startLottery()
    }
    
    if (e.keyCode === 32) {
      switch (currentStatus.value) {
        case 0:
          startLottery()
          break
        case 2:
          stopLottery()
          break
        case 3:
          startLottery()
          break
      }
    }
  })

  window.addEventListener('resize', onWindowResize)

  // 组件卸载时清除事件监听和定时器
  onUnmounted(() => {
    if (socket) {
      socket.disconnect()
    }

    window.removeEventListener('resize', onWindowResize)
    clearInterval(danmakuLoopTimer)
    clearInterval(danmakuRefreshTimer) // 清除新增的弹幕刷新计时器
  })

  // 加载奖品配置
  const savedPrizes = localStorage.getItem('lotteryPrizes')
  if (savedPrizes) {
    try {
      prizes.value = JSON.parse(savedPrizes)
      
      // 修复已保存的奖品图片URL
      const isDev = window.location.port === '5173' // 开发环境端口
      prizes.value.forEach(prize => {
        if (prize.image && prize.image.startsWith('/static/')) {
          // 如果是相对路径且在开发环境，转换为完整URL
          prize.image = isDev 
            ? `http://${window.location.hostname}:3000${prize.image}` 
            : prize.image
        }
      })
    } catch (error) {
      console.error('解析奖品配置失败:', error)
      prizes.value = []
    }
  }
  
  // 如果没有奖品配置，添加一个默认奖项
  if (prizes.value.length === 0) {
    prizes.value.push({
      name: '一等奖',
      count: 1,
      image: '',
      winners: [],
      batchCount: 1
    })
  }
  
  // 加载已保存的中奖名单
  const savedWinners = localStorage.getItem('lotteryWinners')
  if (savedWinners) {
    try {
      winnersList.value = JSON.parse(savedWinners)
      
      // 从中奖名单中提取已中奖的人员ID，以便正确过滤参与者名单
      const winnerIds = new Set(winnersList.value.map(winner => winner.id))
      
      // 覆盖原始的加载函数，以过滤掉已中奖人员
      originalLoadParticipants = async () => {
        try {
          const response = await axios.get('/api/users')
          // 过滤掉已中奖的人员
          participants.value = response.data.filter(p => !winnerIds.has(p.id))
          updateParticipants()
        } catch (error) {
          console.error('获取参与者列表失败:', error)
        }
      }
      
      // 重新加载参与者以应用过滤
      await loadParticipants()
    } catch (error) {
      console.error('解析中奖名单失败:', error)
      winnersList.value = []
    }
  }
})
</script>

<style scoped>
.lottery-container {
  width: 100vw;
  height: 100vh;
  position: relative;
  background: #000;
  transition: background-image 0.3s ease;
}

.lottery-stage {
  width: 100%;
  height: 100%;
  position: relative;
}

.three-container {
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
}

.controls {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  width: 50%;
  padding: 10px;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 10px;
}

.controls button {
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  background: #fff;
  cursor: pointer;
  transition: all 0.3s;
  color: #000;
}

.controls button:hover {
  background: #eee;
}

.controls button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.danmaku-container {
  position: fixed;
  white-space: nowrap;
  will-change: transform;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: hidden;
  z-index: 2000;
  transform: translateZ(0);
}

.danmaku {
  position: fixed;
  white-space: nowrap;
  will-change: transform;
  z-index: 2001;
  font-size: 28px;
  font-weight: bold;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
  pointer-events: none;
  animation: danmaku-move 8s linear;
  animation-fill-mode: forwards;
}

@keyframes danmaku-move {
  from {
    transform: translateX(100vw);
  }
  to {
    transform: translateX(-100%);
  }
}

.winner-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.winner-content {
  background: #fff;
  padding: 40px;
  border-radius: 10px;
  text-align: center;
  width:50vw;
  height:80vh;
}

.winner-content h2 {
  color: #333;
  margin-bottom: 20px;
  font-size: xxx-large;
}

.winner-name {
  font-size: 32px;
  color: #e74c3c;
  margin-bottom: 10px;
  font-size: xxx-large;
}

.winner-dept {
  font-size: 18px;
  color: #666;
  margin-bottom: 10px;
}

.winner-info {
  font-size: 16px;
  color: #666;
  margin-bottom: 5px;
}

.winner-content button {
  padding: 10px 30px;
  font-size: 16px;
  background: #2ecc71;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  margin-top: 15px;
}

.winner-content button:hover {
  background: #27ae60;
}

.participant-name {
  color: #fff;
  font-size: 20px; 
  font-weight: bold;
  padding: 12px 18px;  
  background: rgba(255, 217, 102, 0.95); /* 更鲜艳的黄色背景 */
  border-radius: 8px;
  white-space: nowrap;
  text-align: center;
  cursor: default;
  user-select: none;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); /* 增强阴影效果 */
  transition: transform 0.3s ease;
  margin: 2px;  
  letter-spacing: 1px; 
  border: 2px solid rgba(242, 146, 0, 0.8); /* 添加明显的边框 */
  transform: scale(1.05); /* 稍微放大卡片 */
  position: relative;
  backdrop-filter: blur(3px);
  
  
}

.winners-list {
  position: fixed;
  left: 20px;
  top: 20px;
  width: 20vw; /* 使用视窗宽度的比例而非固定像素 */
  min-width: 200px; /* 设置最小宽度 */
  max-width: 300px; /* 设置最大宽度 */
  background: rgba(0, 0, 0, 0.7);
  border-radius: 10px;
  padding: 15px;
  color: white;
  z-index: 1000;
  font-size: calc(10px + 0.5vw); /* 响应式字体大小 */
}

.winners-list h3 {
  text-align: center;
  margin-bottom: 15px;
  font-size: calc(14px + 0.5vw);
  color: #ffd700;
}

.winners-scroll {
  max-height: 50vh; /* 使用视窗高度而非固定像素 */
  overflow-y: auto;
  padding-right: 10px;
}

.winners-scroll::-webkit-scrollbar {
  width: 6px;
}

.winners-scroll::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 3px;
}

.winners-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.3);
  border-radius: 3px;
}

.winner-item {
  display: flex;
  align-items: center;
  padding: 8px;
  margin-bottom: 8px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  transition: all 0.3s ease;
}

.winner-item:hover {
  background: rgba(255, 255, 255, 0.2);
}

.winner-number {
  font-size: calc(10px + 0.5vw);
  font-weight: bold;
  color: #ffd700;
  margin-right: 10px;
  min-width: 25px;
}

.winner-info {
  flex: 1;
  overflow: hidden; /* 防止长文本溢出 */
}

.winner-info .winner-name {
  font-size: calc(10px + 0.5vw);
  font-weight: bold;
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis; /* 文本过长时显示省略号 */
}

.winner-info .winner-dept {
  font-size: calc(8px + 0.5vw);
  color: rgba(255, 255, 255, 0.7);
}

.winner-prize {
  font-size: calc(8px + 0.5vw);
  color: #ffd700;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis; /* 奖项名称过长时显示省略号 */
}

/* 添加媒体查询，在特别小的屏幕上进一步调整 */
@media screen and (max-width: 768px) {
  .winners-list {
    width: 30vw;
    min-width: 150px;
    padding: 10px;
  }
  
  .winners-scroll {
    max-height: 40vh;
  }
  
  .winner-item {
    padding: 5px;
    margin-bottom: 5px;
  }
}

/* 在特别小的屏幕上进一步缩小 */
@media screen and (max-width: 480px) {
  .winners-list {
    width: 35vw;
    min-width: 120px;
    padding: 8px;
  }
  
  .winners-scroll {
    max-height: 30vh;
  }
}

.bg-settings {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 1000;
  display: flex;
  gap: 10px;
}

.bg-settings button {
  padding: 8px 15px;
  font-size: 14px;
  background: rgba(255, 255, 255, 0.2);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 5px;
  cursor: pointer;
  backdrop-filter: blur(5px);
  transition: all 0.3s ease;
}

.bg-settings button:hover {
  background: rgba(255, 255, 255, 0.3);
}

/* 添加奖品配置面板样式 */
.prize-config-panel {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80%;
  max-width: 600px;
  max-height: 80vh;
  background: rgba(0, 0, 0, 0.8);
  border-radius: 10px;
  padding: 20px;
  color: white;
  z-index: 2000;
  overflow-y: auto;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  padding-bottom: 10px;
}

.panel-header h3 {
  margin: 0;
  color: #ffd700;
}

.close-btn {
  background: none;
  border: none;
  color: white;
  font-size: 24px;
  cursor: pointer;
}

.prize-item {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 15px;
}

.prize-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.prize-header h4 {
  margin: 0;
  color: #ffd700;
}

.remove-btn {
  background: rgba(255, 0, 0, 0.5);
  border: none;
  color: white;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
}

.form-group {
  margin-bottom: 10px;
}

.form-group label {
  display: block;
  margin-bottom: 5px;
  color: rgba(255, 255, 255, 0.8);
}

.form-group input {
  width: 100%;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(0, 0, 0, 0.3);
  color: white;
}

.prize-image-preview {
  margin-top: 10px;
  text-align: center;
}

.prize-image-preview img {
  max-width: 100%;
  max-height: 150px;
  border-radius: 4px;
}

.prize-info {
  margin-bottom: 20px;
  text-align: center;
}

.prize-info h2 {
  color: #ffd700;
  margin-bottom: 15px;
  font-size: xxx-large;
}

.prize-image {
  margin-bottom: 15px;
  text-align: center;
  height: 35vh;
}

.prize-image img {
  max-width: 100%;
  max-height: 35vh;
  border-radius: 8px;
  
}

/* 修改获奖者列表样式，添加奖品信息 */
.winner-item {
  display: flex;
  flex-direction: column;
}

.winner-prize {
  font-size: 14px;
  color: #ffd700;
  margin-top: 4px;
}

/* 添加二维码样式 */
.qrcode-container {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 100;
  background: rgba(255, 255, 255, 0.8);
  padding: 10px;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.qrcode-image {
  width: 15vw;
  height: 20vh;
  object-fit: contain;
  display: block;
}

/* 进入抽奖环节 */
.startbutton-container{
  position: fixed;
  left:50px;
  bottom: 20px;
  transform: translate(-50%, -50%);
  z-index: 100;
  text-align: center;
  width: 100%;
}
.startbutton-container button{
  background: rgba(31, 37, 68, 0.2);
  font-size: 10vh;
  /* border: 3px solid red; */
  border-radius: 15px;
  padding: 20px 40px;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(31, 37, 68, 0.5);
  transition: all 0.3s ease;
}

.startbutton-container button:hover {
  background: rgba(31, 37, 68, 0.4);
  transform: scale(1.05);
  box-shadow: 0 0 50px rgba(31, 37, 68, 0.7);
}

/* 在模板部分添加暂停按钮 */
.stopbutton-container {
  position: fixed;
  bottom: 50px;
  left: 20px;
  z-index: 100;
  /* background: rgba(255, 255, 255, 0.8); */
  padding: 10px;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.stopbutton-container button {
  background: rgba(31, 37, 68, 0.2);
  font-size: 10vh;
  /* border: 3px solid red; */
  border-radius: 15px;
  padding: 20px 40px;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(31, 37, 68, 0.5);
  transition: all 0.3s ease;
}

.stopbutton-container button:hover {
  background: rgba(31, 37, 68, 0.2);
  font-size: 10vh;
  /* border: 3px solid red; */
  border-radius: 15px;
  padding: 20px 40px;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(31, 37, 68, 0.5);
  transition: all 0.3s ease;
}

.defaultbutton-container{
  position: fixed;
  left:50px;
  bottom: 60px;
  transform: translate(-50%, -50%);
  z-index: 100;
  text-align: center;
  width: 100%;
}
.defaultbutton-container button{
  background: rgba(1, 1, 75, 0.2);
  font-size: 3vh;
  color: blue;
  /* border: 3px solid red; */
  border-radius: 15px;
  padding: 20px 40px;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(1, 1, 75, 0.5);
  transition: all 0.3s ease;
}

.defaultbutton-container button:hover {
  background: rgba(1, 1, 75, 0.4);
  transform: scale(1.05);
  box-shadow: 0 0 50px rgba(1, 1, 75, 0.7);
}


/* 批量抽奖弹窗样式 */
.batch-draw-dialog {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1100;
}

.batch-draw-content {
  background: #fff;
  padding: 30px;
  border-radius: 10px;
  text-align: center;
  width: 550px;
  height:400px;
  position: relative; /* 添加相对定位，使关闭按钮可以基于弹窗定位 */
}

.batch-draw-content h3 {
  margin-top: 0;
  color: #333;
  font-size: xx-large;
  margin-bottom: 20px;
}

.prize-name {
  color: #e74c3c;
  font-weight: bold;
}

.prize-count {
  color: #e74c3c;
  font-weight: bold;
}

.batch-input {
  margin: 20px 0;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.batch-input label {
  font-size: x-large;
  color: #333;
}

.batch-input input {
  width: 80px;
  padding: 8px;
  font-size: 18px;
  text-align: center;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.batch-actions {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 20px;
}

.confirm-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: x-large;
}

.confirm-btn {
  background: #2ecc71;
  color: white;
}

.cancel-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  color: #666;
  border: none;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-size: 20px;
  padding: 0;
  transition: all 0.3s ease;
}

.cancel-btn:hover {
  color: #e74c3c;
  background: rgba(0, 0, 0, 0.05);
}

/* 多个获奖者样式 */
.multiple-winners {
  max-height: 300px;
  overflow-y: auto;
  margin: 20px 0;
  padding: 0 10px;
}

.batch-winner-item {
  background: rgba(255, 217, 102, 0.2);
  padding: 10px;
  margin-bottom: 10px;
  border-radius: 5px;
  border-left: 3px solid #e74c3c;
}

.batch-winner-name {
  font-size: 18px;
  color: #e74c3c;
  margin: 0 0 5px 0;
  font-size: xxx-large;
}

.batch-winner-dept {
  font-size: 14px;
  color: #666;
  margin: 0;
}

.reset-btn {
  background: #e67e22;
  color: white;
}

.reset-btn:hover {
  background: #d35400;
}

.export-btn {
  background: #3498db;
  color: white;
}

.export-btn:hover {
  background: #2980b9;
}

.export-btn:disabled {
  background: #95a5a6;
  opacity: 0.5;
  cursor: not-allowed;
}
.element-particles {
  position: absolute;
  width: 100%;
  height: 100%;
  filter: 
    blur(2px)
    drop-shadow(0 0 8px rgba(255,220,150,0.6));
  animation: crystal-float 3s ease-in-out infinite;
}

@keyframes crystal-float {
  0%, 100% { transform: translateY(0) rotate(0); }
  50% { transform: translateY(-8px) rotate(2deg); }
}

@keyframes particle-spin {
  to { 
    transform: 
      rotate(calc(var(--rotate) + 360deg))
      translate(20px)
      scale(0.3);
    opacity: 0;
  }
}
@keyframes rotate {
  from {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}

@keyframes pulse {
  0% { opacity: 0.8; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0.8; transform: scale(1); }
}
@keyframes rotate-glow {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes pulse-glow {
  0% { opacity: 0.8; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0.8; transform: scale(1); }
}
</style> 